package com.pengliu.util;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class AESUtil {
	
	public static String base = "GHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()_+=";
	
	/**
     * AES加密字符串
     * 
     * @param content
     *            需要被加密的字符串
     * @param password
     *            加密需要的密码
     * @return 密文
	 * @throws NoSuchPaddingException 
	 * @throws NoSuchAlgorithmException 
     */
    public static String encrypt(String content, String password) throws Exception {
    	KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者

        kgen.init(128, new SecureRandom(password.getBytes()));// 利用用户密码作为随机数初始化出
                                                                // 128位的key生产者
        //加密没关系，SecureRandom是生成安全随机数序列，password.getBytes()是种子，只要种子相同，序列就一样，所以解密只要有password就行

        SecretKey secretKey = kgen.generateKey();// 根据用户密码，生成一个密钥

        byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥，如果此密钥不支持编码，则返回null。

        SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥

        Cipher cipher = Cipher.getInstance("AES");// 创建密码器

        byte[] byteContent = content.getBytes("utf-8");

        cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化为加密模式的密码器

        byte[] result = cipher.doFinal(byteContent);// 加密

        return parseByte2HexStr(result);
    }
    
    /**
     * 解密AES加密过的字符串
     * 
     * @param content
     *            AES加密过过的内容
     * @param password
     *            加密时的密码
     * @return 明文
     * @throws Exception 
     */
    public static String decrypt(String content, String password) throws Exception {
    	byte[] contentKyte = parseHexStr2Byte(content);
    	KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
        kgen.init(128, new SecureRandom(password.getBytes()));
        SecretKey secretKey = kgen.generateKey();// 根据用户密码，生成一个密钥
        byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥
        SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
        Cipher cipher = Cipher.getInstance("AES");// 创建密码器
        cipher.init(Cipher.DECRYPT_MODE, key);// 初始化为解密模式的密码器
        byte[] result = cipher.doFinal(contentKyte);  
        return new String(result); // 明文   
    }
    
    /**将二进制转换成16进制 
     * @param buf 
     * @return 
     */  
    private static String parseByte2HexStr(byte buf[]) {  
            StringBuffer sb = new StringBuffer();  
            for (int i = 0; i < buf.length; i++) {  
                    String hex = Integer.toHexString(buf[i] & 0xFF);  
                    if (hex.length() == 1) {  
                            hex = '0' + hex;  
                    }  
                    sb.append(hex.toUpperCase());  
            }  
            return sb.toString();  
    } 
    
    /**将16进制转换为二进制 
     * @param hexStr 
     * @return 
     */  
    private static byte[] parseHexStr2Byte(String hexStr) {  
            if (hexStr.length() < 1)  
                    return null;  
            byte[] result = new byte[hexStr.length()/2];  
            for (int i = 0;i< hexStr.length()/2; i++) {  
                    int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);  
                    int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);  
                    result[i] = (byte) (high * 16 + low);  
            }  
            return result;  
    }
    
    /**
     * user: pengliu
     * date: 2018年11月7日
     * desc: 随机特殊字符加密
     * @author pengliu
     * @throws Exception 
     */
    public static String randomStringEncrypt(String content, String password) throws Exception {
    	StringBuilder contentBuilder = new StringBuilder(encrypt(content, password));
    	return forSubString(contentBuilder);
    }
    
    private static String forSubString(StringBuilder content) {
    	int strLength = content.length();
    	content.insert(RandomUtil.getRangeRandom(1, strLength-1), RandomUtil.getRandomString(base, 1));
    	if(content.length()>=254) {
    		return content.toString()+"==";
    	}
    	return forSubString(content);
    }
    
    public static String randomStringDecrypt(String content, String password) throws Exception {
    	return decrypt(content.replaceAll("[^0-9A-F]+", ""), password);
    }
    
    public static void main(String[] args) throws Exception {
		String content = "4AG43B3294CF31F4363048F59814954AD8912F2616BF8DE6607E49E20CA9110CBFB2A612F708841806B5FE6269358F2582F589BC5F1FB0593B6D8FFDF77D1E5BBA001B93823EC97E896ED30AE288ACA4E67EFD6EE35C4D46A616EFA676B1378E58A0611737021361C6C7A6DB3300CF1820E6B3741C5C5C888B4782F82939EF6F15F323FF4E968208C30C670D4DC4CAFD2004F6790B36971E9FA351EFE9ABAB624A03BA40A78BECF255D14511CB0E8EC1CED5631D56779769AFD32CD8DFF0AB7A9==";
		
		String str = randomStringDecrypt(content, "bac851884cc642828304459516666a77");
		System.out.println(str);
	}
}
